﻿/**
* 提供对LoadBox的控制
*
* @Experience
 * 当同时有多个LoadBox时,通过LoadManager对所有的LoadBox进行控制先后加载(顺序加载).
 * 
 * 1、当uid已经存在时,
*/

package org.nickro.project.manager{
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.display.Sprite;
	import flash.errors.IOError;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLRequest;
	import flash.utils.Dictionary;
	
	import org.nickro.project.load.LoadBox;
	import org.nickro.project.load.LoadMode;
	import org.nickro.project.events.LoadEvent;
	import org.nickro.project.debug.Console;
	public class LoadManager extends EventDispatcher
	{
		private static var _instance:LoadManager
		
		private var pLoaderDict:Dictionary = new Dictionary(true);
		private var pLoaders:Array = [];
		//加载断点
		private var breakPoint:int = 0;
		//替换加载的上一加载地址
		private var pPrevURL:String = "";
		
		public function LoadManager(singleton:SingletonEnforcer)
		{
		}
		
		public static function getInstance():LoadManager
		{
			if(LoadManager._instance == null)
			{
				_instance = new LoadManager(new SingletonEnforcer());
			}
			return LoadManager._instance;
		}
		/**
		 * 
		 * @param	loader
		 * @param	uid			与url同步，因为url的值唯一.
		 * @param	mode
		 * @return
		 */
		public function addLoadBox(loader:Loader,uid:String,mode:String = LoadMode.NONE):Boolean
		{
			var obj:Object = { };
			obj.uid = uid;
			obj.target = loader;
			pLoaders.push(obj);
			pLoaderDict[uid] = obj;
			configEventListener(loader.contentLoaderInfo);
			switch(mode) {
				case 'none':			normalLoad(uid); break;
				case 'line':			loopLoad(); break;
				case 'replace':			replaceLoad(uid); break;
			}
			return true;
		}
		/**----------------------------------------------------
		 * 顺序加载
		 ------------------------------------------------------*/
		 private var _urls:Array;
		 public function lineLoad(a:Array):void
		 {
			 _urls = a;
			 
		 }
		//循环加载
		private function loopLoad():void
		{
			start(pLoaders[0].uid);
			pLoaders[0].target.addEventListener(LoadEvent.COMPLETE,onLineComplete);
		}
		//插入加载
		public function insertLoad(uid:String):void
		{
			if (pLoaders.length > 0) {
				if (pLoaderDict[uid]) {
					Console.info("[LoadManager] :: insertLoad URL == " + uid);
					stop(pLoaders[0].uid);
					start(pLoaderDict[uid].uid);
					pLoaderDict[uid].target.addEventListener(LoadEvent.COMPLETE, onPointComplete);
				}else {
					throw new Error(uid + " is not exist!plz check it out.");
				}
			}else {
				//all Content has been loaded!,so not need to insertLoad
				Console.info("Debug [LoadManager] :: All content has loaded,so no stuff to insertLoad.");
			}
		}
		//循环加载结束
		private function onLineComplete(e:LoadEvent):void
		{
			e.currentTarget.removeEventListener(LoadEvent.COMPLETE,onLineComplete);	
			//发送LoadEvent.COMPLETE事件
			dispatchEvent(new LoadEvent(LoadEvent.COMPLETE, e.data));
			//完成一个则移除掉相关的loader,包括pLoaders和pLoaderDict
			pLoaders.shift();
			
			
			if (pLoaders.length > 0) {
				loopLoad();
			}
		}
		//插入加载结束
		private function onPointComplete(e:LoadEvent):void
		{
			e.currentTarget.removeEventListener(LoadEvent.COMPLETE, onPointComplete);
			e.currentTarget.dispachEvent(new LoadEvent(LoadEvent.COMPLETE, e.data));
			//var pInsertIndex:int = pLoaders.indexOf(pLoaderDict[uid]);
		}
		//----------------------Splitted Line------------------------------//
		/**----------------------------------------------------------------
		 * 替换加载
		 -----------------------------------------------------------------*/
		private function replaceLoad(url:String):void
		{
			if (pPrevURL != null && pPrevURL != "") {
				Console.info('[LoadManager] :: ' + pLoaderDict[pPrevURL]);
				deleteLoad(pPrevURL);
			}
			pPrevURL = url;
		}
		 
		//移除兼通
		private function deleteLoad(url:String):void
		{
			//if (Loader(pLoaders[url]).unLoaded) {
				//容错
				try {
					stop(url);
					delete(pLoaderDict[url].target);
				}catch (e:Error) {
					//trace("URLStream没有打开的流.");
				}
			//}
		}
		//------------------Splitted Line--------------------------------------//
		/**
		 * 一般加载
		 */
		private function normalLoad(uid:String):void
		{
			start(pLoaders[0].uid);
			pLoaders[0].target.addEventListener(LoadEvent.COMPLETE,onLineComplete);
		}
		/**-----------------------------------------
		 * 功能性函数部分
		 --------------------------------------------*/
		//开始加载操作
		public function start(url):void
		{
			pLoaderDict[url].target.load(new URLRequest(url));
			configEventListener(pLoaderDict[url].target.contentLoaderInfo);
		}
		//停止加载操作
		public function stop(url):void
		{
			deleteEventListener(pLoaders[url].target.contentLoaderInfo);
			pLoaderDict[url].target.close();
		}
		//移除loader
		public function die(url):void
		{
			deleteEventListener(pLoaders[url].target.contentLoaderInfo);
		}
		
		private function getUIDFromTarget(target:Loader):void
		{
			
		}
		
		/**------------------------------------------------
		 * 事件监听及处理
		 ------------------------------------------------*/
		private function configEventListener(dispatcher:IEventDispatcher):void
		{
			dispatcher.addEventListener(ProgressEvent.PROGRESS,onProgress);
			dispatcher.addEventListener(Event.COMPLETE,onComplete);
			dispatcher.addEventListener(IOErrorEvent.IO_ERROR,onIOError);
			dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecError);
		}
		
		private function deleteEventListener(dispatcher:IEventDispatcher):void
		{
			dispatcher.removeEventListener(ProgressEvent.PROGRESS,onProgress);
			dispatcher.removeEventListener(Event.COMPLETE,onComplete);
			dispatcher.removeEventListener(IOErrorEvent.IO_ERROR,onIOError);
			dispatcher.removeEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecError);
		}
		private function onProgress(e:ProgressEvent):void
		{
			var percent:int = int((e.bytesLoaded / e.bytesTotal) * 100);
			//LoaderInfo(e.target).loader.dispatchEvent(new LoadEvent(LoadEvent.PROGRESS, percent));
		}
		private function onComplete(e:Event):void
		{
			var content:* = e.target.content;
			LoaderInfo(e.target).loader.dispatchEvent(new LoadEvent(LoadEvent.COMPLETE,content));
			deleteEventListener(e.currentTarget as LoaderInfo);
		}
		
		private function onIOError(e:IOErrorEvent):void
		{
			//trace(e.target.url);
			throw new IOError('"' + e.target.loaderURL + '"'+ " is not existed");
		}
		
		private function onSecError(e:SecurityErrorEvent):void
		{
			throw new SecurityError(this + "安全问题");
		}
	}
}
class SingletonEnforcer { };